home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Mac-Source 1994 July
/
Mac-Source_July_1994.iso
/
C and C++
/
Science⁄Math
/
Scientist's Helper src
/
s.helper.5
/
regspline.c
< prev
next >
Wrap
C/C++ Source or Header
|
1986-02-06
|
8KB
|
317 lines
#include "all.h"
#include "regtabext.h"
LoadSg3() /*force load of segment*/
{
;
}
Spline( X,Y, N, C, X0,Y0, F, AM,BM,CM,DM,EM,FM, LAST ) /* natural cubic splines */
float X[], Y[], C[], X0, *Y0, AM[], BM[], CM[], DM[], EM[], FM[];
int N, F, *LAST;
/* X THE ARRAY OF X VALUES ARRANGED IN ORDER OF INCREASING X VALUE WITH NO DUPLICATIONS
Y THE ARRAY OF Y VALUES
N THE NUMBER OF (X,Y) PAIRS
C AN ARRAY INTO WHICH THE SPLINE COEFFICIENTS ARE STORED
X0 AN ARBITRARY X VALUE AT WHICH THE SPLINE IS TO BE EVALUATED
Y0 POINTER TO RETURN THE VALUE OF Y AT X0
F A FLAG, COMPUTE COEFFICIENTS ON TRUE, EVALUATE SPLINE AT X0 ON FALSE
AM TEMP ARRAY OF LENGTH N+2
BM TEMP ARRAY OF LENGTH N+2
CM TEMP ARRAY OF LENGTH N+2
DM TEMP ARRAY OF LENGTH N+2
EM TEMP ARRAY OF LENGTH N+2
FM TEMP ARRAY OF LENGTH N+2
LAST POINTER TO INTEGER FOR TEMPORARY STORAGE */
{
int I, J, JP1;
float HJ;
char s[80];
if (F) { /* compute spline coefficients */
*LAST=1;
for (I=2; I<=(N-1); I++ ) {
X0 = (Y[I+1]-Y[I])/(X[I+1]-X[I]);
X0 = X0 - (Y[I]-Y[I-1])/(X[I]-X[I-1]);
DM[I-1] = 6.0*X0;
BM[I-1] = 2.0*(X[I+1]-X[I-1]);
AM[I-1] = X[I+1] - X[I];
}
TRIDI(AM,BM,CM,DM,C,N-2,EM,FM);
C[N]=0.0; /* SHIFT ALL THE C'S AND SET C(1)=C(N)=0.0 */
for( I=2; I<=(N-1); I++ ) {
J = N-I;
C[J+1]=C[J];
}
C[1] = 0.0;
} /*end if compute spline coefficients*/
else { /* evaluate spline at X0 */
/* locate proper knot */
if( (X0<=X[(*LAST)+1]) && (X0>=X[*LAST]) ) { /*check current knot*/
J = *LAST;
JP1 = J+1;
} /*end if*/
else { /*check elsewhere*/
(*LAST)++;
if ( (*LAST)>(N+1) ) *LAST=N+1;
if ( (X0<=X[(*LAST)+1]) && (X0>=X[*LAST]) ) { /*check next knot*/
J = *LAST;
JP1 = J+1;
}
else if (X0<X[1]) { /*check off beginning*/
J = 1;
JP1 = 2;
}
else if (X0>X[N]) { /*check off end*/
J = N-1;
JP1 = N;
}
else { /*scan all knots*/
for( I=1; I<=(N-1); I++ ) {
if( (X0<=X[I+1]) && (X0>=X[I]) ) {
J=I;
JP1=I+1;
break;
} /*end if in interval*/
} /*end for*/
} /*end else*/
} /*end if*/
*LAST = J;
/* COMPUTE Y0 AT X0 */
HJ = X[JP1] - X[J];
*Y0 = (C[J]/(6.0*HJ)) * (X[JP1]-X0)*(X[JP1]-X0)*(X[JP1]-X0);
*Y0 += (C[JP1]/(6.0*HJ)) * (X0-X[J])*(X0-X[J])*(X0-X[J]);
*Y0 += (Y[JP1]/HJ-C[JP1]*HJ/6.0) * (X0-X[J]);
*Y0 += (Y[J]/HJ-C[J]*HJ/6.0) * (X[JP1]-X0);
} /*end if evaluate spline*/
}
SplInterpolate()
{
float *xd, *yd, *c, *am, *bm, *cm, *dm, *em, *fm; /*temporary arrays*/
float firstX, lastX, x0, y0;
int npair, col, i, j, k, newRows, oldRows, last, goodX;
long bytesNeeded;
char str[cmdWordLen];
if( table.header.interpolated ) {
ErrMsg("table already interpolated");
}
if( table.header.rows < 4 ) {
ErrMsg("not enough rows");
}
if( table.header.cols < 2 ) {
ErrMsg("not enough cols");
}
SToR( command.cmdWord[1], &(table.header.samp), FALSE );
if (table.header.samp<=0) {
table.header.samp = 1.0;
ErrMsg("samp must be > 0");
}
/* find first non-NaN x value */
j=FALSE;
for( i=1; i<=table.header.rows; i++ ) {
GetTable( i, 1, &firstX );
if( !NaN(&firstX) ) {
j=TRUE;
k=i;
break;
} /*end if*/
} /*end for*/
if( (!j) || (k==table.header.rows) ) ErrMsg("not enough data in col 1");
/* find last non-NaN x value */
for( i=table.header.rows; i>=1; i-- ) {
GetTable( i, 1, &lastX );
if( !NaN(&lastX) ) {
break;
} /*end if*/
} /*end for*/
/* count up non-NaN x values */
goodX=0;
for( i=1; i<=table.header.rows; i++ ) {
GetTable( i, 1, &x0 );
if( !NaN(&x0) ) {
goodX++;
} /*end if*/
} /*end for*/
if( goodX<4 ) ErrMsg("not enough data in col 1");
/* check for points that are out of order */
x0 = firstX;
for( i=k+1; i<=table.header.rows; i++ ) {
GetTable( i, 1, &y0 );
if( !NaN(&y0) ) {
if( y0<=x0 ) ErrMsg("data in col 1 out of order");
x0 = y0;
} /*end if*/
} /*end for*/
bytesNeeded = 4L * (4+goodX);
if( (xd=NewPtr(bytesNeeded)) == 0L ) {
ErrMsg("not enough free memory");
}
if( (yd=NewPtr(bytesNeeded)) == 0L ) {
DisposPtr(xd);
ErrMsg("not enough free memory");
}
if( (c=NewPtr(bytesNeeded)) == 0L ) {
DisposPtr(xd);
DisposPtr(yd);
ErrMsg("not enough free memory");
}
if( (am=NewPtr(bytesNeeded)) == 0L ) {
DisposPtr(xd);
DisposPtr(yd);
DisposPtr(c);
ErrMsg("not enough free memory");
}
if( (bm=NewPtr(bytesNeeded)) == 0L ) {
DisposPtr(xd);
DisposPtr(yd);
DisposPtr(c);
DisposPtr(am);
ErrMsg("not enough free memory");
}
cm = am-1;
if( (dm=NewPtr(bytesNeeded)) == 0L ) {
DisposPtr(xd);
DisposPtr(yd);
DisposPtr(c);
DisposPtr(am);
DisposPtr(bm);
ErrMsg("not enough free memory");
}
if( (em=NewPtr(bytesNeeded)) == 0L ) {
DisposPtr(xd);
DisposPtr(yd);
DisposPtr(c);
DisposPtr(am);
DisposPtr(bm);
DisposPtr(dm);
ErrMsg("not enough free memory");
}
if( (fm=NewPtr(bytesNeeded)) == 0L ) {
DisposPtr(xd);
DisposPtr(yd);
DisposPtr(c);
DisposPtr(am);
DisposPtr(bm);
DisposPtr(dm);
DisposPtr(em);
ErrMsg("not enough free memory");
}
table.header.start = firstX;
x0 = 1.0 + ((lastX-firstX)/table.header.samp);
oldRows = table.header.rows;
if ( ((long)x0) > ((long)table.header.maxRows) ) {
WriteLine("warning. some data lost from end of columns");
newRows = table.header.maxRows;
} /*end if*/
else {
newRows= (int)x0;
} /*end if*/
for (col=2; col<=table.header.cols; col++ ) {
/* stuff arrays xd and yd with non-Nan data */
i=1;
npair=0;
while( NextNotNan( i, 1, col, &i ) ) {
npair++;
GetTable( i, 1, (xd+npair) );
GetTable( i, col, (yd+npair) );
i++;
} /*end while*/
if (npair<4) {
IToS( col, str );
WritePhrase("warning: not enough data in col ");
WriteLine(str);
table.header.rows = newRows;
for( j=1; j<=table.header.rows; j++ ) {
SetTable(j,col,infinity,FALSE);
}
table.header.rows=oldRows;
} /*end if pairs<4*/
else { /*npair>=4*/
Spline( xd,yd, npair, c, x0,&y0, TRUE, am,bm,cm,dm,em,fm, &last );
for( i=1; i<=newRows; i++ ) {
x0 = table.header.start + table.header.samp*((float)(i-1));
Spline( xd,yd, npair, c, x0,&y0, FALSE, am,bm,cm,dm,em,fm, &last );
table.header.rows = newRows;
SetTable( i, col, y0, FALSE );
table.header.rows = oldRows;
} /*end for i*/
} /*end if pairs>=4*/
} /*end for col*/
table.header.interpolated=TRUE;
table.header.rows = newRows;
Header2Vars();
CreateCol1();
DisposPtr(xd);
DisposPtr(yd);
DisposPtr(c);
DisposPtr(am);
DisposPtr(bm);
DisposPtr(dm);
DisposPtr(em);
DisposPtr(fm);
}
TRIDI( A,B,C, D, T, N, E,F ) /* solves tri-diagonal matrix equation */
float A[], B[], C[], D[], T[], E[], F[];
int N;
/*THE MATRIX EQUATION SOLVED IS :
( B1 A1 0 0 0 0 . ) ( T1 ) ( D1 )
( ) ( ) ( )
( C2 B2 A2 0 0 0 . ) ( T2 ) ( D2 )
( ) ( ) ( )
( 0 C3 B3 A3 0 0 . ) ( T3 ) = ( D3 )
( ) ( ) ( )
( 0 0 C4 B4 A4 0 . ) ( T4 ) ( D4 )
( ) ( ) ( )
( . . . . . . . ) ( . ) ( . )
( ) ( ) ( )
( 0 0 0 0 0 CN BN ) ( TN ) ( DN )
E, F are temp arrays of length N+2 */
{
int I, J;
float TEMP;
E[1] = -A[1]/B[1];
F[1] = D[1]/B[1];
for( I=2; I<=(N-1); I++ ) {
TEMP = B[I] + C[I] * E[I-1];
E[I] = - A[I] / TEMP;
F[I] = ( D[I] - C[I]*F[I-1] ) / TEMP;
} /*end for*/
T[N] = (D[N]/C[N]-F[N-1]) / (E[N-1]+B[N]/C[N]);
for( J=1; J<=N-1; J++ ) {
I=N-J;
T[I] = E[I] * T[I+1] + F[I];
} /* end for */
}